
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Diagnostics;

namespace Swaf.Call
{
	/// <summary>
	/// Summary description for BaseCallbackQueue.
	/// </summary>
	public class BaseCallbackQueue : ICallbackQueue
	{
        protected Queue m_callQueue;
        protected bool m_isShutdown = false;
        protected object syncObject = new object();

		public BaseCallbackQueue()
		{
			m_callQueue = new Queue();
		}

        public bool IsShutdown
        {
            get
            {
                lock (syncObject)
                {
                    return m_isShutdown;
                }
            }
            set
            {
                lock (syncObject)
                {
                    m_isShutdown = value;
                }
            }
        }
		public virtual void enqueueCall(ICall call)
		{
			Debug.Assert(call != null, "null values shouldn't be passed to enqueueCall");
			lock(m_callQueue)
			{
				m_callQueue.Enqueue(new CallInfo(call, null));
			}
		}

		public virtual void enqueueCall(ICall call, params object[] info)
		{
			lock(m_callQueue)
			{
				m_callQueue.Enqueue(new CallInfo(call, info));
			}
		}

		protected int processQueue()
		{
			int processed = 0;
			while(m_callQueue.Count > 0)
			{
                if (IsShutdown) break;

				++processed;
				CallInfo nextCall = null;
				lock(m_callQueue)
				{
					nextCall = (CallInfo)m_callQueue.Dequeue();
				}
				Debug.Assert(nextCall != null, "Nothing but valid ICall objects should be in CallbackQueue.m_callQueue");
				try
				{
					if(nextCall.Info == null)
						nextCall.Call.call();
					else
						nextCall.Call.call(nextCall.Info);
				}
				catch(Exception e)
				{
					//TODO Log exception occuring within callback.
				}
			}
			return processed;
		}

		private class CallInfo
		{
			public ICall Call;
			public object[] Info;
			public CallInfo(ICall call, object[] info)
			{
				Call = call; Info = info;
			}
		}
	}
}
